home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / system / map20.zip / MAP.C < prev    next >
C/C++ Source or Header  |  1994-10-27  |  34KB  |  1,152 lines

  1. // --------------------------------------------------------------------------
  2. //
  3. //  File:      MAP.C
  4. //  Author:    Sulyok Peter (C) 1992,1994.
  5. //  Compiler:  Borland C++ 3.1 (COMPACT model with byte alignment)
  6. //  Notes:     Memory map.
  7. //
  8. // --------------------------------------------------------------------------
  9.  
  10. // Include files ------------------------------------------------------------
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <dos.h>
  14. #include <mem.h>
  15. #include <string.h>
  16.  
  17. // Constants ----------------------------------------------------------------
  18. #define uchar        unsigned char
  19. #define ushort       unsigned int
  20. #define ulong        unsigned long
  21.  
  22. #define FALSE        0
  23. #define TRUE         1
  24.  
  25. #define MAX_ITEM     150
  26. #define MAX_VEC      100
  27. #define MAX_DRIVE    20
  28. #define MAX_HANDLE   255
  29.  
  30. #define MT_NONE      0
  31. #define MT_SYSCODE   1
  32. #define MT_SYSDATA   2
  33. #define MT_PROGRAM   3
  34. #define MT_DEVICE    4
  35. #define MT_ENV       5
  36. #define MT_DATA      6
  37. #define MT_FREE      7
  38. #define MT_MAP       8
  39.  
  40. #define NORMAL       0
  41. #define UPPER        1
  42.  
  43. #define USAGE        "MAP 2.0, memory map utility, Sulyok Peter (C) 1992,1994.\n" \
  44.                      "Usage:   MAP [-option ...]\n" \
  45.                      "Options:\n" \
  46.                      "         -n    list of programs in normal memory (default)\n" \
  47.                      "         -u    list of programs in normal and upper memory\n" \
  48.                      "         -f    full list of memory blocks\n" \
  49.                      "         -d    list of device drivers\n" \
  50.                      "         -x    XMS report\n" \
  51.                      "         -e    EMS report\n" \
  52.                      "         -h,?  this text"
  53.  
  54. // Types --------------------------------------------------------------------
  55.  
  56. // Structure of device driver header.
  57. typedef struct device_header {
  58.    struct device_header *next;
  59.    ushort attr;
  60.    ushort strategy_rutin;
  61.    ushort interrupt_rutin;
  62.    uchar  name[8];
  63. } DEVICE_HEADER;
  64.  
  65. // Structure of device driver information.
  66. typedef struct {
  67.    struct device_header *addr;
  68.    uchar  devname[9];
  69.    uchar  progname[9];
  70.    ushort attr;
  71.    uchar  drive_num;
  72.    uchar  drives[MAX_DRIVE];
  73. } DINFO;
  74.  
  75. // Structure of DOS DPB.
  76. typedef struct dpb {
  77.    uchar  drive_num;
  78.    uchar  unit_number;
  79.    ushort bytes_in_sector;
  80.    uchar  lsec_num;
  81.    uchar  log_base;
  82.    ushort reserved_num;
  83.    uchar  FAT_num;
  84.    ushort rootentry_num;
  85.    ushort first_sector;
  86.    ushort largest_cluster;
  87.    ushort sectors_in_FAT;
  88.    ushort root_firstsector;
  89.    DEVICE_HEADER *device_addr;
  90.    uchar  media_desc;
  91.    uchar  block_flag;
  92.    struct dpb *next_dpb;
  93. } DPB;
  94.  
  95. // Internal structure of DOS DATA blocks.
  96. typedef struct {
  97.    uchar type;
  98.    ushort start;
  99.    ushort size;
  100.    uchar  unused[3];
  101.    uchar  name[8];
  102. } SD_HEADER;
  103.  
  104. // Stucture of MCB header.
  105. typedef struct {
  106.    uchar  type;
  107.    ushort owner;
  108.    ushort size;
  109.    uchar  unused[3];
  110.    uchar  name[8];
  111. } MCB;
  112.  
  113. // Structure of programs, device drivers, memory blocks information.
  114. typedef struct {
  115.    uchar  type;
  116.    ushort seg;
  117.    ushort owner;
  118.    ushort environment;
  119.    uchar  name[10];
  120.    ulong  size;
  121.    uchar  vecnum;
  122.    uchar  vectors[MAX_VEC];
  123. } MINFO;
  124.  
  125. // Structure of allocated EMS handles.
  126. typedef struct {
  127.    ushort handle;
  128.    ushort pages;
  129. } EMS_HANDLE;
  130.  
  131. // Structure of allocated XMS handles.
  132. typedef struct {
  133.    ushort handle;
  134.    ulong  size;
  135.    ushort locks;
  136. } XMS_HANDLE;
  137.  
  138. // Local variables ----------------------------------------------------------
  139. static uchar  copyright[]=
  140.    "Sulyok Péter (C) 1992,1994.";
  141.  
  142. static MCB   *first_mcb=NULL;
  143. static MINFO  mlist[MAX_ITEM];
  144. static ushort mlistnum=0;
  145. static DEVICE_HEADER *first_dev=NULL;
  146. static DPB    *first_dpb=NULL;
  147. static DINFO  dlist[MAX_ITEM];
  148. static ushort dlistnum=0;
  149. static uchar *typenames[]=
  150.    {
  151.     "             ",
  152.     "system code  ",
  153.     "system data  ",
  154.     "program      ",
  155.     "device driver",
  156.     "environment  ",
  157.     "data area    ",
  158.     "free         ",
  159.    };
  160.  
  161. static uchar  ems_installed=FALSE;
  162. static uchar  ems_name[]="EMMXXXX0";
  163. static ushort ems_frame=0;
  164. static uchar  ems_vermajor=0;
  165. static uchar  ems_verminor=0;
  166. static ulong  ems_size=0L;
  167. static ulong  ems_free=0L;
  168. static ushort ems_totalhandle=0;
  169. static ushort ems_freehandle=0;
  170. static ushort ems_usehandle=0;
  171. static EMS_HANDLE ems_handles[MAX_HANDLE];
  172.  
  173. static uchar  xms_installed=FALSE;
  174. static void far (*xms_drv)(void);
  175. static ulong  xms_free=0L;
  176. static ulong  xms_largest=0L;
  177. static uchar  xms_vermajor=0;
  178. static uchar  xms_verminor=0;
  179. static uchar  xms_hma=0;
  180. static uchar  xms_a20=0;
  181. static XMS_HANDLE xms_handles[MAX_HANDLE];
  182. static ushort xms_usehandle=0;
  183. static ushort xms_freehandle=0;
  184.  
  185. static uchar  upper_installed=FALSE;
  186. static ulong  upper_free=0L;
  187. static ulong  upper_large=0L;
  188. static ushort upper_index=0;
  189.  
  190. // Local functions ----------------------------------------------------------
  191. static void   check_ems(void);
  192. static void   check_xms(void);
  193. static void   check_upper(void);
  194. static void   check_memory(void);
  195. static uchar  get_upperlink(void);
  196. static int    set_upperlink(uchar);
  197. static void   search_vectors(MINFO *);
  198. static void   search_sd(MCB *);
  199. static void   register_mcb(MCB *);
  200. static int    is_psp(MCB *);
  201. static ushort env_seg(MCB *);
  202. static void   make_mcb_list(void);
  203. static void   make_dev_list(void);
  204. static void   normal_list(uchar type);
  205. static void   full_list(void);
  206. static void   device_list(void);
  207. static void   ems_list(void);
  208. static void   xms_list(void);
  209.  
  210. // --------------------------------------------------------------------------
  211. //  Name:      check_ems
  212. //  Input:     -
  213. //  Output:    -
  214. //  Notes:     Checks EMS memory and gets EMS parameters.
  215. // --------------------------------------------------------------------------
  216. static void check_ems(void)
  217. {
  218.    void far *int67;
  219.  
  220.    int67=(void *)getvect(0x67);
  221.    if (int67 == NULL)
  222.       return;
  223.  
  224.    asm   push  ds
  225.    asm   push  si
  226.    asm   push  di
  227.    asm   les   di,int67
  228.    asm   mov   di,10
  229.    asm   lea   si,ems_name
  230.    asm   mov   cx,8
  231.    asm   cld
  232.    asm   repe  cmpsb
  233.    asm   pop   di
  234.    asm   pop   si
  235.    asm   pop   ds
  236.    asm   jz    _found
  237.    return;
  238.  
  239.    _found:
  240.    ems_installed=TRUE;
  241.  
  242.    asm   mov   ah,41h
  243.    asm   int   67h
  244.    asm   or    ah,ah
  245.    asm   jnz   _error
  246.    asm   mov   ems_frame,bx
  247.  
  248.    asm   mov   ah,46h
  249.    asm   int   67h
  250.    asm   or    ah,ah
  251.    asm   jnz   _error
  252.    asm   mov   bl,al
  253.    asm   and   al,0fh
  254.    asm   and   bl,0f0h
  255.    asm   mov   cl,4
  256.    asm   shr   bl,cl
  257.    asm   mov   ems_vermajor,bl
  258.    asm   mov   ems_verminor,al
  259.  
  260.    asm   mov   ah,42h
  261.    asm   int   67h
  262.    asm   or    ah,ah
  263.    asm   jnz   _error
  264.    asm   mov   word ptr ems_size,dx
  265.    asm   mov   word ptr ems_size[2],0
  266.    asm   mov   word ptr ems_free,bx
  267.    asm   mov   word ptr ems_free[2],0
  268.    ems_size*=16384L;
  269.    ems_free*=16384L;
  270.  
  271.    asm   push  di
  272.    _ES=FP_SEG(&ems_handles);
  273.    _DI=FP_OFF(&ems_handles);
  274.    asm   mov   ah,4Dh
  275.    asm   int   67h
  276.    asm   pop   di
  277.    asm   or    ah,ah
  278.    asm   jnz   _error
  279.    asm   mov   ems_usehandle,bx
  280.  
  281.    if (ems_vermajor >= 4) {
  282.       asm   mov   ax,5402h
  283.       asm   int   67h
  284.       asm   or    ah,ah
  285.       asm   jnz   _error
  286.       asm   mov   ems_totalhandle,bx
  287.    } else {
  288.       ems_totalhandle=ems_usehandle;
  289.       }
  290.  
  291.    ems_freehandle=ems_totalhandle - ems_usehandle;
  292.    return;
  293.  
  294.    _error:
  295.    puts("EMS INTERNAL ERROR.");
  296.    exit(1);
  297. }
  298.  
  299. // --------------------------------------------------------------------------
  300. //  Name:      check_xms
  301. //  Input:     -
  302. //  Output:    -
  303. //  Notes:     Checks XMS memory and gets XMS parameters.
  304. // --------------------------------------------------------------------------
  305. static void check_xms(void)
  306. {
  307.    asm   mov   ax,4300h
  308.    asm   int   2fh
  309.    asm   cmp   al,80h
  310.    asm   je    _found
  311.    return;
  312.  
  313.    _found:
  314.    xms_installed=TRUE;
  315.  
  316.    asm   mov   ax,4310h
  317.    asm   int   2fh
  318.    asm   mov   word ptr xms_drv,bx
  319.    asm   mov   word ptr xms_drv[2],es
  320.  
  321.    asm   mov   ah,0
  322.    (*xms_drv)();
  323.    asm   mov   xms_vermajor,ah
  324.    asm   mov   xms_verminor,al
  325.    asm   mov   xms_hma,dl
  326.  
  327.    asm   mov   ah,8
  328.    (*xms_drv)();
  329.    asm   mov   word ptr xms_free,ax
  330.    asm   mov   word ptr xms_free[2],0
  331.    asm   mov   word ptr xms_largest,dx
  332.    asm   mov   word ptr xms_largest[2],0
  333.    xms_free*=1024L;
  334.    xms_largest*=1024L;
  335.  
  336.    asm   mov   ah,7
  337.    (*xms_drv)();
  338.    asm   or    bl,bl
  339.    asm   jnz   _error
  340.    asm   mov   xms_a20,al
  341.    return;
  342.  
  343.    _error:
  344.    puts("XMS INTERNAL ERROR.");
  345.    exit(1);
  346. }
  347.  
  348. // --------------------------------------------------------------------------
  349. //  Name:      get_upperlink
  350. //  Input:     -
  351. //  Output:    uchar             0   separated upper and normal blocks
  352. //                               1   linked upper and normal blocks
  353. //  Notes:     Checks the connection of normal and upper memory blocks.
  354. // --------------------------------------------------------------------------
  355. static uchar get_upperlink(void)
  356. {
  357.    asm   mov   ax,5802h
  358.    asm   int   21h
  359.    return(_AL);
  360. }
  361.  
  362. // --------------------------------------------------------------------------
  363. //  Name:      set_upperlink
  364. //  Input:     uchar link        0   separate it
  365. //                               1   link it
  366. //  Output:    int               1   successful
  367. //                               0   there is no upper memory
  368. //                              -1   system memory is trashed
  369. //  Notes:     Set the connection between upper and normal memory
  370. //             blocks.
  371. // --------------------------------------------------------------------------
  372. static int set_upperlink(uchar link)
  373. {
  374.    asm   mov   ax,5803h
  375.    asm   xor   bh,bh
  376.    asm   mov   bl,link
  377.    asm   int   21h
  378.    asm   jc    _noumb
  379.  
  380.    return(1);
  381.  
  382.    _noumb:
  383.    asm   cmp   ax,1
  384.    asm   jne   _trash
  385.    return(0);
  386.  
  387.    _trash:
  388.    return(-1);
  389. }
  390.  
  391. // --------------------------------------------------------------------------
  392. //  Name:      check_upper
  393. //  Input:     -
  394. //  Output:    -
  395. //  Notes:     Checks upper memory.
  396. // --------------------------------------------------------------------------
  397. static void check_upper(void)
  398. {
  399.    uchar origlink;
  400.  
  401.    origlink=get_upperlink();
  402.    switch(set_upperlink(1)) {
  403.       case 1:
  404.          upper_installed=TRUE;
  405.          break;
  406.  
  407.       case 0:
  408.          upper_installed=FALSE;
  409.          break;
  410.  
  411.       case -1:
  412.          puts("SYSTEM MEMORY TRASHED!");
  413.          exit(1);
  414.          break;
  415.       }
  416.    set_upperlink(origlink);
  417. }
  418.  
  419. // --------------------------------------------------------------------------
  420. //  Name:      check_memory
  421. //  Input:     -
  422. //  Output:    -
  423. //  Notes:     Checks EMS, XMS, upper memory.
  424. // --------------------------------------------------------------------------
  425. static void check_memory(void)
  426. {
  427.    check_ems();
  428.    check_xms();
  429.    check_upper();
  430. }
  431.  
  432. // --------------------------------------------------------------------------
  433. //  Name:      is_psp
  434. //  Input:     MCB *mcb       address of the MSC structure
  435. //  Output:    int            TRUE  it is a program
  436. //                            FALSE it is a simple MCB block
  437. //  Notes:     Checks the PSP of given MCB block.
  438. // --------------------------------------------------------------------------
  439. static int is_psp(MCB *mcb)
  440. {
  441.    asm   les   bx,mcb
  442.    asm   mov   ax,es
  443.    asm   inc   ax
  444.    asm   mov   es,ax
  445.    asm   mov   ax,TRUE
  446.    asm   cmp   word ptr es:[bx],20CDh
  447.    asm   je    __exit
  448.    asm   mov   ax,FALSE
  449.  
  450.    __exit:
  451.    return(_AX);
  452. }
  453.  
  454. // --------------------------------------------------------------------------
  455. //  Name:      env_seg
  456. //  Input:     MCB *mcb       address of MCB block
  457. //  Output:    ushort         segment of enviroment
  458. //  Notes:     Returns the segment of the given MCB block.
  459. // --------------------------------------------------------------------------
  460. static ushort env_seg(MCB *mcb)
  461. {
  462.    MCB *env;
  463.  
  464.    asm   les   bx,mcb
  465.    asm   mov   ax,es
  466.    asm   inc   ax
  467.    asm   mov   es,ax
  468.    asm   mov   bx,ax
  469.    asm   mov   ax,es:[2Ch]
  470.    asm   dec   ax
  471.    asm   mov   es,ax
  472.    asm   inc   ax
  473.    asm   cmp   es:[1],bx
  474.    asm   je    __exit
  475.    asm   mov   ax,0
  476.  
  477.    __exit:
  478.    return(_AX);
  479. }
  480.  
  481. // --------------------------------------------------------------------------
  482. //  Name:      search_vectors
  483. //  Input:     MINFO *m       address of a memory block
  484. //  Output:    -
  485. //  Notes:     Searches interrupt vectors of the given memory block.
  486. // --------------------------------------------------------------------------
  487. static void search_vectors(MINFO *m)
  488. {
  489.    ushort i;
  490.    ulong  begin, end, iv;
  491.    uchar far *ivp;
  492.  
  493.    begin=(ulong)(m->seg + 1) << 4;
  494.    end=begin + m->size;
  495.    for(i=0; i<256; i++) {
  496.       memcpy(&ivp, MK_FP(0, i*4), 4);
  497.       iv=((ulong)(FP_SEG(ivp) + 1) << 4) + (ulong)FP_OFF(ivp);
  498.       if ((iv > begin) && (iv < end) && (m->vecnum < MAX_VEC))
  499.          m->vectors[m->vecnum++]=(uchar)i;
  500.       }
  501. }
  502.  
  503. // --------------------------------------------------------------------------
  504. //  Name:      search_sd
  505. //  Input:     MCB *mcb       address of MCB block
  506. //  Output:    -
  507. //  Notes:     Searches the internal parts of a DOS data block.
  508. // --------------------------------------------------------------------------
  509. static void search_sd(MCB *mcb)
  510. {
  511.    ushort     begin, end;
  512.    SD_HEADER *sd;
  513.  
  514.    sd=MK_FP(FP_SEG(mcb) + 1, 0);
  515.    begin=FP_SEG(mcb);
  516.    end=FP_SEG(mcb) + mcb->size;
  517.    while((FP_SEG(sd) > begin) &&
  518.          (FP_SEG(sd) < end) &&
  519.          (mlistnum < MAX_ITEM)) {
  520.       mlistnum++;
  521.       mlist[mlistnum].seg=sd->start;
  522.       mlist[mlistnum].size=(ulong)sd->size << 4;
  523.       switch(sd->type) {
  524.          case 'D':
  525.          case 'I':
  526.             mlist[mlistnum].name[0]=' ';
  527.             strncpy(&mlist[mlistnum].name[1], sd->name, 8);
  528.             strupr(mlist[mlistnum].name);
  529.             mlist[mlistnum].type=MT_DEVICE;
  530.             break;
  531.  
  532.          case 'F':
  533.             strcpy(mlist[mlistnum].name, " FILES");
  534.             mlist[mlistnum].type=MT_DATA;
  535.             break;
  536.  
  537.          case 'X':
  538.             strcpy(mlist[mlistnum].name, " FCBS");
  539.             mlist[mlistnum].type=MT_DATA;
  540.             break;
  541.  
  542.          case 'C':
  543.          case 'B':
  544.             strcpy(mlist[mlistnum].name, " BUFFERS");
  545.             mlist[mlistnum].type=MT_DATA;
  546.             break;
  547.  
  548.          case 'L':
  549.             strcpy(mlist[mlistnum].name, " LASTDRV");
  550.             mlist[mlistnum].type=MT_DATA;
  551.             break;
  552.  
  553.          case 'S':
  554.             strcpy(mlist[mlistnum].name, " STACKS");
  555.             mlist[mlistnum].type=MT_DATA;
  556.             break;
  557.  
  558.          default:
  559.             strcpy(mlist[mlistnum].name, " ??????");
  560.             mlist[mlistnum].type=MT_DATA;
  561.             break;
  562.          }
  563.       sd=MK_FP(sd->start + sd->size, 0);
  564.       }
  565. }
  566.  
  567. // --------------------------------------------------------------------------
  568. //  Name:      check_name
  569. //  Input:     uchar *name    name of MCB or device driver
  570. //  Output:    -
  571. //  Notes:     Filters name of MCBs and device drivers.
  572. // --------------------------------------------------------------------------
  573. void check_name(uchar *name)
  574. {
  575.    ushort i;
  576.  
  577.    for(i=0; name[i]; i++)
  578.       if ( name[i] < ' ' ) {
  579.          name[i] = '\0';
  580.          break;
  581.          } // if
  582. }
  583.  
  584. // --------------------------------------------------------------------------
  585. //  Name:      register_mcb
  586. //  Input:     MCB *mcb       address of MCB block
  587. //  Output:    -
  588. //  Notes:     Registers parameters of the given MCB block.
  589. // --------------------------------------------------------------------------
  590. static void register_mcb(MCB *mcb)
  591. {
  592.    mlist[mlistnum].seg=FP_SEG(mcb);
  593.    mlist[mlistnum].owner=mcb->owner;
  594.    mlist[mlistnum].size=(ulong)mcb->size << 4;
  595.  
  596.    if (mlist[mlistnum].seg <= 0x9FFF) {
  597.       if (is_psp(mcb)) {
  598.          strncpy(mlist[mlistnum].name, mcb->name, 8);
  599.          check_name(mlist[mlistnum].name);
  600.          strupr(mlist[mlistnum].name);
  601.          mlist[mlistnum].environment=env_seg(mcb);
  602.          mlist[mlistnum].type=MT_PROGRAM;
  603.          }
  604.       if (!mcb->owner) {
  605.          mlist[mlistnum].type=MT_FREE;
  606.       } else if (mcb->owner <= 0x0008) {
  607.          strcpy(mlist[mlistnum].name, "DOS");
  608.          if (!strncmp(mcb->name, "SD", 2)) {
  609.             mlist[mlistnum].type=MT_SYSDATA;
  610.             search_sd(mcb);
  611.          } else if (!strncmp(mcb->name, "SC", 2)) {
  612.             mlist[mlistnum].type=MT_SYSCODE;
  613.             }
  614.          else
  615.             mlist[mlistnum].type=MT_SYSCODE;
  616.          }
  617.  
  618.    } else {
  619.       if (!mcb->owner) {
  620.          mlist[mlistnum].type=MT_FREE;
  621.       } else if (mcb->owner <= 0x0008) {
  622.          strcpy(mlist[mlistnum].name, "DOS");
  623.          if (!strncmp(mcb->name, "SD", 2)) {
  624.             mlist[mlistnum].type=MT_SYSDATA;
  625.             search_sd(mcb);
  626.          } else if (!strncmp(mcb->name, "SC", 2)) {
  627.             mlist[mlistnum].type=MT_SYSCODE;
  628.             }
  629.       } else if (mcb->owner > 0x0008) {
  630.          mlist[mlistnum].environment=env_seg(mcb);
  631.          mlist[mlistnum].type=MT_PROGRAM;
  632.          strncpy(mlist[mlistnum].name, mcb->name, 8);
  633.          strupr(mlist[mlistnum].name);
  634.          }
  635.       }
  636. }
  637.  
  638. // --------------------------------------------------------------------------
  639. //  Name:      make_mcb_list
  640. //  Input:     -
  641. //  Output:    -
  642. //  Notes:     Makes the list of MCBs.
  643. // --------------------------------------------------------------------------
  644. static void make_mcb_list(void)
  645. {
  646.    ushort i, j;
  647.    MCB   *cur_mcb;
  648.    uchar  origlink;
  649.  
  650.    memset(mlist, 0, sizeof(mlist));
  651.    check_memory();
  652.  
  653.    asm   mov   ah,52h
  654.    asm   int   21h
  655.    asm   mov   ax,es:[bx-2]
  656.    asm   mov   word ptr first_mcb[2],ax
  657.    asm   mov   word ptr first_mcb,0
  658.  
  659.    if (upper_installed) {
  660.       origlink=get_upperlink();
  661.       set_upperlink(1);
  662.       }
  663.  
  664.    cur_mcb=(MCB *)MK_FP(first_mcb, 0);
  665.    while((mlistnum < MAX_ITEM) && (cur_mcb->type != 'Z')) {
  666.       register_mcb(cur_mcb);
  667.       cur_mcb=(MCB *)MK_FP(FP_SEG(cur_mcb) + cur_mcb->size + 1, 0);
  668.       ++mlistnum;
  669.       }
  670.  
  671.    register_mcb(cur_mcb);
  672.    cur_mcb=(MCB *)MK_FP(FP_SEG(cur_mcb) + cur_mcb->size + 1, 0);
  673.    ++mlistnum;
  674.  
  675.    if (upper_installed)
  676.       set_upperlink(origlink);
  677.  
  678.    for(i=0; i<mlistnum; i++)
  679.       if ( (mlist[i].seg >= 0x9000) && (mlist[i].seg <= 0xB000) &&
  680.            (mlist[i].type == MT_SYSCODE) ) {
  681.          upper_index=i;
  682.          break;
  683.          }
  684.  
  685.    for(i=upper_index; i<mlistnum; i++)
  686.       if (mlist[i].type == MT_FREE) {
  687.          upper_free+=mlist[i].size;
  688.          if (mlist[i].size > upper_large)
  689.             upper_large=mlist[i].size;
  690.          }
  691.  
  692.    for(i=0; i<mlistnum; i++) {
  693.       if (mlist[i].type == MT_PROGRAM)
  694.          for(j=0; j<mlistnum; j++)
  695.             if ((mlist[i].seg != mlist[j].seg) &&
  696.                 (mlist[j].owner == mlist[i].seg+1)) {
  697.                strcpy(mlist[j].name, mlist[i].name);
  698.                mlist[j].type=(mlist[i].environment == mlist[j].seg+1) ? MT_ENV : MT_DATA;
  699.                }
  700.       if (mlist[i].type != MT_SYSDATA)
  701.          search_vectors(&mlist[i]);
  702.       }
  703.  
  704.    for(i=0; i<mlistnum; i++)
  705.       if (mlist[i].seg+1 == _psp) {
  706.          mlist[i+1].size+=mlist[i].size + 16;
  707.          mlist[i].type=MT_MAP;
  708.          for(j=0; j<mlistnum; j++)
  709.             if (mlist[j].seg+1 == mlist[i].environment) {
  710.                if (j == i-1) {
  711.                   mlist[j].type=MT_MAP;
  712.                } else {
  713.                   mlist[j].type=MT_FREE;
  714.                   mlist[j].name[0]='\0';
  715.                   }
  716.                break;
  717.                }
  718.          break;
  719.          }
  720. }
  721.  
  722. // --------------------------------------------------------------------------
  723. //  Name:      make_dev_list
  724. //  Input:     -
  725. //  Output:    -
  726. //  Notes:     Makes list of device drivers.
  727. // --------------------------------------------------------------------------
  728. static void make_dev_list(void)
  729. {
  730.    ushort         i, j;
  731.    DEVICE_HEADER *cur_dev;
  732.    DPB           *cur_dpb;
  733.  
  734.    memset(dlist, 0, sizeof(dlist));
  735.    make_mcb_list();
  736.  
  737.    asm   mov   ah,52h
  738.    asm   int   21h
  739.    asm   add   bx,22h
  740.    asm   mov   word ptr first_dev[2],es
  741.    asm   mov   word ptr first_dev,bx
  742.  
  743.    cur_dev=first_dev;
  744.    while((FP_OFF(cur_dev) != 0xFFFF) &&
  745.          (dlistnum < MAX_ITEM)) {
  746.       dlist[dlistnum].addr=cur_dev;
  747.       dlist[dlistnum].attr=cur_dev->attr;
  748.       strncpy(dlist[dlistnum].devname, cur_dev->name, 8);
  749.       check_name(dlist[dlistnum].devname);
  750.       strupr(dlist[dlistnum].devname);
  751.       cur_dev=cur_dev->next;
  752.       ++dlistnum;
  753.       }
  754.  
  755.    for(i=0; i<dlistnum; i++)
  756.       for(j=0; j<mlistnum; j++)
  757.          if (mlist[j].seg == FP_SEG(dlist[i].addr))
  758.             strcpy(dlist[i].progname, (mlist[j].name[0] == ' ') ?
  759.                    &mlist[j].name[1] : mlist[j].name);
  760.  
  761.    asm   mov   ah,52h
  762.    asm   int   21h
  763.    asm   les   bx,es:[bx]
  764.    asm   mov   word ptr first_dpb[2],es
  765.    asm   mov   word ptr first_dpb,bx
  766.  
  767.    cur_dpb=first_dpb;
  768.    while(FP_OFF(cur_dpb) != 0xFFFF) {
  769.       for(i=0; i<dlistnum; i++)
  770.          if (dlist[i].addr == cur_dpb->device_addr) {
  771.             dlist[i].drives[dlist[i].drive_num++]=cur_dpb->drive_num+'A';
  772.             break;
  773.             }
  774.       cur_dpb=cur_dpb->next_dpb;
  775.       }
  776.  
  777.    for(i=0; i<dlistnum; i++) {
  778.       if ((dlist[i].attr & 0x8000) == 0)
  779.          dlist[i].devname[0]='\0';
  780.       if (dlist[i].drive_num) {
  781.          if (dlist[i].drive_num == 1)
  782.             sprintf(dlist[i].devname, "%c:", dlist[i].drives[0]);
  783.          else
  784.             sprintf(dlist[i].devname, "%c: - %c:", dlist[i].drives[0],
  785.                     dlist[i].drives[dlist[i].drive_num-1]);
  786.          }
  787.       }
  788. }
  789.  
  790. // --------------------------------------------------------------------------
  791. //  Name:      normal_list
  792. //  Input:     uchar type     type of list
  793. //  Output:    -
  794. //  Notes:     Displays the normal list of programs.
  795. // --------------------------------------------------------------------------
  796. static void normal_list(uchar type)
  797. {
  798.    ushort i, num;
  799.  
  800.    make_mcb_list();
  801.  
  802.    puts("┌───────────────────────────────────────────┐");
  803.    puts("│ mcb    size     name        type          │");
  804.    puts("├──────┬────────┬───────────┬───────────────┤");
  805.    num=(upper_installed && (type == NORMAL)) ? upper_index : mlistnum;
  806.    for(i=0; i<num; i++)
  807.       if ((mlist[i].type == MT_SYSCODE) ||
  808.           (mlist[i].type == MT_SYSDATA) ||
  809.           (mlist[i].type == MT_FREE) ||
  810.           (mlist[i].type == MT_PROGRAM) ||
  811.           (mlist[i].type == MT_DEVICE))
  812.          printf("│ %04x │ %6lu │ %-9s │ %-13s │\n",
  813.                 mlist[i].seg, mlist[i].size, mlist[i].name,
  814.                 typenames[mlist[i].type]);
  815.  
  816.    if (!ems_installed && !xms_installed && !upper_installed) {
  817.       puts("└──────┴────────┴───────────┴───────────────┘");
  818.       return;
  819.       }
  820.  
  821.    puts("├──────┴────────┴───────────┴───────────────┤");
  822.  
  823.    if (ems_installed)
  824.       printf("│  %8lu bytes free EMS memory           │\n", ems_free);
  825.  
  826.    if (xms_installed)
  827.       printf("│  %8lu bytes free XMS memory           │\n", xms_free);
  828.  
  829.    if (upper_installed)
  830.       printf("│  %8lu bytes free upper memory         │\n", upper_free);
  831.  
  832.    puts("└───────────────────────────────────────────┘");
  833. }
  834.  
  835. // --------------------------------------------------------------------------
  836. //  Name:      full_list
  837. //  Input:     -
  838. //  Output:    -
  839. //  Notes:     Displays full list of memory blocks.
  840. // --------------------------------------------------------------------------
  841. static void full_list(void)
  842. {
  843.    ushort i, j, pos;
  844.    uchar  line[81];
  845.  
  846.    make_mcb_list();
  847.  
  848.    puts("┌────────────────────────────────────────────────────────────────────────┐");
  849.    puts("│ mcb    size     name        type            interrupt vectors          │");
  850.    puts("├──────┬────────┬───────────┬───────────────┬────────────────────────────┤");
  851.    for(i=0; i<mlistnum; i++)
  852.       if (mlist[i].type != MT_MAP) {
  853.          sprintf(line, "│ %04x │ %6lu │ %-9s │ %-4s │                            │",
  854.                mlist[i].seg, mlist[i].size, mlist[i].name,
  855.                typenames[mlist[i].type]);
  856.          for(j=1, pos=46; j<=mlist[i].vecnum; j++) {
  857.             sprintf(&line[pos], "%02x", (int)mlist[i].vectors[j-1]);
  858.             line[pos+2]=' ';
  859.             if (!(j % 9) && ((j+1) <= mlist[i].vecnum)) {
  860.                puts(line);
  861.                strcpy(line, "│      │        │           │               │                            │");
  862.                pos=46;
  863.             } else {
  864.                pos+=3;
  865.                }
  866.             }
  867.          puts(line);
  868.          }
  869.  
  870.    puts("└──────┴────────┴───────────┴───────────────┴────────────────────────────┘");
  871. }
  872.  
  873. // --------------------------------------------------------------------------
  874. //  Name:      device_list
  875. //  Input:     -
  876. //  Output:    -
  877. //  Notes:     Display the list of device drivers.
  878. // --------------------------------------------------------------------------
  879. static void device_list(void)
  880. {
  881.    ushort i, num;
  882.  
  883.    make_dev_list();
  884.  
  885.    puts("┌────────────────────────────────────────┐");
  886.    puts("│ address     attr   name       program  │");
  887.    puts("├───────────┬──────┬──────────┬──────────┤");
  888.        //  XXXX:XXXX   XXXX   XXXXXXXX   XXXXXXXX
  889.    for(i=0; i<dlistnum; i++)
  890.          printf("│ %Fp │ %04x │ %-8s │ %-8s │\n",
  891.                 dlist[i].addr, dlist[i].attr, dlist[i].devname,
  892.                 dlist[i].progname);
  893.  
  894.    puts("└───────────┴──────┴──────────┴──────────┘");
  895. }
  896.  
  897. // --------------------------------------------------------------------------
  898. //  Name:      ems_list
  899. //  Input:     -
  900. //  Output:    -
  901. //  Notes:     Displays the EMS report.
  902. // --------------------------------------------------------------------------
  903. static void ems_list(void)
  904. {
  905.    ushort i;
  906.    uchar *line, numstr[20];
  907.    uchar  handlename[9];
  908.  
  909.    check_ems();
  910.  
  911.    puts("┌─────────────────────────────────────┐");
  912.  
  913.    if (!ems_installed) {
  914.       puts("│ EMS driver not installed in system. │");
  915.    } else {
  916.       line="│ EMS driver version                  │";
  917.       sprintf(numstr, "%1i.%1i", (int)ems_vermajor, (int)ems_verminor);
  918.       strncpy(&line[22], numstr, strlen(numstr));
  919.       puts(line);
  920.  
  921.       line="│ EMS page frame                      │";
  922.       sprintf(numstr, "%04X", ems_frame);
  923.       strncpy(&line[22], numstr, strlen(numstr));
  924.       puts(line);
  925.  
  926.       line="│ Total EMS memory                    │";
  927.       sprintf(numstr, "%lu bytes", ems_size);
  928.       strncpy(&line[22], numstr, strlen(numstr));
  929.       puts(line);
  930.  
  931.       line="│ Free EMS memory                     │";
  932.       sprintf(numstr, "%lu bytes", ems_free);
  933.       strncpy(&line[22], numstr, strlen(numstr));
  934.       puts(line);
  935.  
  936.       line="│ Total handles                       │";
  937.       sprintf(numstr, "%u", ems_totalhandle);
  938.       strncpy(&line[22], numstr, strlen(numstr));
  939.       puts(line);
  940.  
  941.       line="│ Free handles                        │";
  942.       sprintf(numstr, "%u", ems_freehandle);
  943.       strncpy(&line[22], numstr, strlen(numstr));
  944.       puts(line);
  945.  
  946.       puts("│                                     │");
  947.       puts("│  Handle  Pages  Size      Name      │");
  948.       puts("│ ─────────────────────────────────── │");
  949.       for(i=0; i<ems_usehandle; i++) {
  950.          memset(handlename, 0, sizeof(handlename));
  951.          if (ems_vermajor >= 4) {
  952.             if (ems_handles[i].handle == 0) {
  953.                strcpy(handlename, "SYSTEM");
  954.             } else {
  955.                asm   push  di
  956.                _DX=ems_handles[i].handle;
  957.                _ES=FP_SEG(&handlename);
  958.                _DI=FP_OFF(&handlename);
  959.                asm   mov   ax,5300h
  960.                asm   int   67h
  961.                asm   pop   di
  962.                }
  963.             strupr(handlename);
  964.             }
  965.          printf("│  %-7u %-6u %-9lu %-9s │\n",
  966.                 ems_handles[i].handle, ems_handles[i].pages,
  967.                 (ulong)ems_handles[i].pages * 16384L, handlename);
  968.          }
  969.  
  970.       }
  971.    puts("└─────────────────────────────────────┘");
  972. }
  973.  
  974. // --------------------------------------------------------------------------
  975. //  Name:      xms_list
  976. //  Input:     -
  977. //  Output:    -
  978. //  Notes:     Displays the XMS report.
  979. // --------------------------------------------------------------------------
  980. static void xms_list(void)
  981. {
  982.    ushort i;
  983.    uchar *line, numstr[20];
  984.  
  985.    make_mcb_list();
  986.  
  987.    if (xms_installed) {
  988.       printf("Testing XMS memory ...");
  989.       memset(xms_handles, 0, sizeof(xms_handles));
  990.       xms_usehandle=0;
  991.       for(i=0; i<65535; i++) {
  992.          asm   mov   ah,0Eh
  993.          _DX=i;
  994.          (*xms_drv)();
  995.          asm   or    ax,ax
  996.          asm   jnz   _found
  997.          continue;
  998.  
  999.          _found:
  1000.          asm   mov   byte ptr xms_freehandle,bl
  1001.          if (xms_usehandle < MAX_HANDLE) {
  1002.             asm   push  di
  1003.             _ES=FP_SEG(&xms_handles);
  1004.             _DI=FP_OFF(&xms_handles);
  1005.             asm   mov   ax,xms_usehandle  // xms_handles[xms_usehandle].handle=i;
  1006.             asm   mov   cl,3
  1007.             asm   shl   ax,cl
  1008.             asm   add   di,ax
  1009.             asm   mov   ax,i
  1010.             asm   mov   es:[di],ax
  1011.             asm   mov   es:[di+2],dx      // xms_handles[xms_usehandle].size=_DX;
  1012.             asm   mov   es:[di+6],bh      // xms_handles[xms_usehandle].locks=_BH;
  1013.             asm   pop   di
  1014.             xms_handles[xms_usehandle].size*=1024L;
  1015.             xms_usehandle++;
  1016.             }
  1017.          }
  1018.       printf("\r");
  1019.       }
  1020.  
  1021.    puts("┌────────────────────────────────────────┐");
  1022.  
  1023.    if (!xms_installed) {
  1024.       puts("│ XMS driver not installed in system.    │");
  1025.    } else {
  1026.       line="│ XMS driver version                     │";
  1027.       sprintf(numstr, "%i.%i", (ushort)xms_vermajor, (ushort)xms_verminor);
  1028.       strncpy(&line[26], numstr, strlen(numstr));
  1029.       puts(line);
  1030.  
  1031.       line="│ HMA state                              │";
  1032.       sprintf(numstr, "%s", (xms_hma) ? "exists" : "not exists");
  1033.       strncpy(&line[26], numstr, strlen(numstr));
  1034.       puts(line);
  1035.  
  1036.       line="│ A20 line state                         │";
  1037.       sprintf(numstr, "%s", (xms_a20) ? "enabled" : "disabled");
  1038.       strncpy(&line[26], numstr, strlen(numstr));
  1039.       puts(line);
  1040.  
  1041.       line="│ Free XMS memory                        │";
  1042.       sprintf(numstr, "%lu bytes", xms_free);
  1043.       strncpy(&line[26], numstr, strlen(numstr));
  1044.       puts(line);
  1045.  
  1046.       line="│ Largest free XMS block                 │";
  1047.       sprintf(numstr, "%lu bytes", xms_largest);
  1048.       strncpy(&line[26], numstr, strlen(numstr));
  1049.       puts(line);
  1050.  
  1051.       line="│ Free handles                           │";
  1052.       sprintf(numstr, "%u", xms_freehandle);
  1053.       strncpy(&line[26], numstr, strlen(numstr));
  1054.       puts(line);
  1055.  
  1056.       if (xms_usehandle) {
  1057.          puts("│                                        │");
  1058.          puts("│  Block  Handle  Size      Locks        │");
  1059.          puts("│ ────────────────────────────────────── │");
  1060.          for(i=0; i<xms_usehandle; i++)
  1061.             printf("│  %-6u %-7u %-9lu %-12u │\n",
  1062.                   i, xms_handles[i].handle, xms_handles[i].size,
  1063.                   xms_handles[i].locks);
  1064.          }
  1065.  
  1066.       puts("│                                        │");
  1067.       if (upper_installed) {
  1068.          line="│ Free upper memory                      │";
  1069.          sprintf(numstr, "%lu bytes", upper_free);
  1070.          strncpy(&line[26], numstr, strlen(numstr));
  1071.          puts(line);
  1072.          line="│ Largest upper block                    │";
  1073.          sprintf(numstr, "%lu bytes", upper_large);
  1074.          strncpy(&line[26], numstr, strlen(numstr));
  1075.          puts(line);
  1076.       } else {
  1077.          puts("│ Upper memory            not available  │");
  1078.          }
  1079.       }
  1080.  
  1081.    puts("└────────────────────────────────────────┘");
  1082. }
  1083.  
  1084. // Main ---------------------------------------------------------------------
  1085. int main(int argc, char *argv[])
  1086. {
  1087.    ushort i;
  1088.  
  1089.    if ( (_osmajor != 5) && (_osmajor != 6 ) ) {
  1090.       puts("This program runs under DOS 5.x or 6.x versions.");
  1091.       return 1;
  1092.       }
  1093.  
  1094.    if (argc > 1) {
  1095.       for(i=1; i<argc; i++) {
  1096.          if ((argv[i][0] == '-') || (argv[i][0] == '/'))
  1097.             switch( argv[i][1] ) {
  1098.                case 'n':
  1099.                case 'N':
  1100.                   normal_list(NORMAL);
  1101.                   break;
  1102.  
  1103.                case 'u':
  1104.                case 'U':
  1105.                   normal_list(UPPER);
  1106.                   break;
  1107.  
  1108.                case 'f':
  1109.                case 'F':
  1110.                   full_list();
  1111.                   break;
  1112.  
  1113.                case 'd':
  1114.                case 'D':
  1115.                   device_list();
  1116.                   break;
  1117.  
  1118.                case 'e':
  1119.                case 'E':
  1120.                   ems_list();
  1121.                   break;
  1122.  
  1123.                case 'x':
  1124.                case 'X':
  1125.                   xms_list();
  1126.                   break;
  1127.  
  1128.                case 'h':
  1129.                case 'H':
  1130.                case '?':
  1131.                   puts(USAGE);
  1132.                   return 0;
  1133.  
  1134.                default:
  1135.                   printf("Invalid option %s (use -h for help).\n", argv[i]);
  1136.                   return 1;
  1137.                }
  1138.  
  1139.          else {
  1140.             printf("Invalid option %s (use -h for help).\n", argv[i]);
  1141.             return 1;
  1142.             }
  1143.          }
  1144.    } else {
  1145.       normal_list(NORMAL);
  1146.       }
  1147.  
  1148.    return 0;
  1149. }
  1150.  
  1151. // End ----------------------------------------------------------------------
  1152.